Tegra: Add support for fake system suspend
authorVignesh Radhakrishnan <[email protected]>
Fri, 3 Mar 2017 18:58:05 +0000 (10:58 -0800)
committerVarun Wadekar <[email protected]>
Thu, 13 Apr 2017 21:18:42 +0000 (14:18 -0700)
This patch adds support for fake system suspend (SC7).
This is a debug mode, to ensure that a different code path is
executed for cases like pre-silicon development, where a
full-fledged SC7 is not possible in early stages.

This particular patch ensures that, if fake system suspend is
enabled (denoted by tegra_fake_system_suspend variable
having a non-zero value), instead of calling WFI, a request
for a warm reset is made for starting the SC7 exit procedure.

This ensures that the code path of kernel->ATF and back to
kernel is executed without depending on other components
involved in SC7 code path.

Additionally, this patch also adds support for SMC call
from kernel, enabling fake system suspend mode.

Signed-off-by: Vignesh Radhakrishnan <[email protected]>
Signed-off-by: Varun Wadekar <[email protected]>
include/lib/aarch64/arch.h
plat/nvidia/tegra/common/tegra_pm.c
plat/nvidia/tegra/common/tegra_sip_calls.c
plat/nvidia/tegra/include/tegra_private.h

index a2c736c9903bb7ff50e621ba9ddebc68aa9c616c..d766490d17312825296e37c2bcacbd7cb9a3042f 100644 (file)
 
 #define EC_BITS(x)                     (x >> ESR_EC_SHIFT) & ESR_EC_MASK
 
+/* Reset bit inside the Reset management register for EL3 (RMR_EL3) */
+#define RMR_RESET_REQUEST_SHIFT        0x1u
+#define RMR_WARM_RESET_CPU             (1u << RMR_RESET_REQUEST_SHIFT)
+
 /*******************************************************************************
  * Definitions of register offsets, fields and macros for CPU system
  * instructions.
index 5376d5231fa2e6f1374ba6a68ba41798a3775f44..d6329268954dab0cdef29c9eb42f72d6e93db5a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -48,6 +48,14 @@ extern uint64_t tegra_bl31_phys_base;
 extern uint64_t tegra_sec_entry_point;
 extern uint64_t tegra_console_base;
 
+/*
+ * tegra_fake_system_suspend acts as a boolean var controlling whether
+ * we are going to take fake system suspend code or normal system suspend code
+ * path. This variable is set inside the sip call handlers,when the kernel
+ * requests a SIP call to set the suspend debug flags.
+ */
+uint8_t tegra_fake_system_suspend;
+
 /*
  * The following platform setup functions are weakly defined. They
  * provide typical implementations that will be overridden by a SoC.
@@ -182,14 +190,31 @@ void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
 __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t
                                             *target_state)
 {
+       uint8_t pwr_state = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
+       uint64_t rmr_el3 = 0;
+
        /* call the chip's power down handler */
        tegra_soc_pwr_domain_power_down_wfi(target_state);
 
-       /* enter power down state */
-       wfi();
+       /*
+        * If we are in fake system suspend mode, ensure we start doing
+        * procedures that help in looping back towards system suspend exit
+        * instead of calling WFI by requesting a warm reset.
+        * Else, just call WFI to enter low power state.
+        */
+       if ((tegra_fake_system_suspend != 0U) &&
+           (pwr_state == (uint8_t)PSTATE_ID_SOC_POWERDN)) {
+
+               /* warm reboot */
+               rmr_el3 = read_rmr_el3();
+               write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU);
+
+       } else {
+               /* enter power down state */
+               wfi();
+       }
 
        /* we can never reach here */
-       ERROR("%s: operation not handled.\n", __func__);
        panic();
 }
 
index 4dd43532b93fd2d415a69879e3c647f1d4720df1..b01dcb0cf69dd7764297ec5bb2a865e2cde0ea7d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -37,6 +37,7 @@
 #include <memctrl.h>
 #include <runtime_svc.h>
 #include <tegra_private.h>
+#include <tegra_platform.h>
 
 /*******************************************************************************
  * Common Tegra SiP SMCs
 #define TEGRA_SIP_NEW_VIDEOMEM_REGION          0x82000003
 #define TEGRA_SIP_FIQ_NS_ENTRYPOINT            0x82000005
 #define TEGRA_SIP_FIQ_NS_GET_CONTEXT           0x82000006
+#define TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND   0xC2000007
+
+/*******************************************************************************
+ * Fake system suspend mode control var
+ ******************************************************************************/
+extern uint8_t tegra_fake_system_suspend;
+
 
 /*******************************************************************************
  * SoC specific SiP handler
@@ -144,6 +152,26 @@ uint64_t tegra_sip_handler(uint32_t smc_fid,
                SMC_RET0(handle);
                break;
 
+       case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND:
+               /*
+                * System suspend fake mode is set if we are on VDK and we make
+                * a debug SIP call. This mode ensures that we excercise debug
+                * path instead of the regular code path to suit the pre-silicon
+                * platform needs. These include replacing the call to WFI by
+                * a warm reset request.
+                */
+               if (tegra_platform_is_emulation() != 0U) {
+
+                       tegra_fake_system_suspend = 1;
+                       SMC_RET1(handle, 0);
+               }
+
+               /*
+                * We return to the external world as if this SIP is not
+                * implemented in case, we are not running on VDK.
+                */
+               break;
+
        default:
                ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
                break;
index 39006f6faf24d6e954334490da9e8e05846b2e57..edd1f65d62375a8f60341d73b262f605061e6bcc 100644 (file)
@@ -103,6 +103,8 @@ void tegra_security_setup(void);
 void tegra_security_setup_videomem(uintptr_t base, uint64_t size);
 
 /* Declarations for tegra_pm.c */
+extern uint8_t tegra_fake_system_suspend;
+
 void tegra_pm_system_suspend_entry(void);
 void tegra_pm_system_suspend_exit(void);
 int tegra_system_suspended(void);